/******************************************************************************
秋夜静，独坐对残灯。
啼笑非非谁识我，坐行梦梦尽缘君，何所慰消沉。
风卷雨，雨复卷侬心。
心似欲随风雨去，茫茫大海任浮沉。
无爱亦无恨。
******************************************************************************/
#include "kbRGB_Int.h"
#include <math.h>
#include "Effects/kbRGB_Int/kbRGB_Int_Effect.h"

/*************************************************************************************************\
|        ColorWheel [9]                                                                           |
\*************************************************************************************************/
void kbRGB_Int_ColorWheel_Init(struct kbRGB_Int_Params *const params)       // 色轮
{
    params->Speed = 80-15;
    params->Slider2Val = 50;
}
static uint32_t ColorWheelEffect_GetColor(const uint16_t x, const uint16_t y, const int16_t w, const int16_t h, const int32_t _progress, const int reverse)
{
    //float direction_mult = -1.0f;//direction == 0 ? 1.f : -1.f;
    //double angle;
    //struct kbRGB_Pixel piont;
    int16_t dx = w - x*2;
    int16_t dy = h - y*2;
    uint32_t hue;// = (float)(progress + (int)(180 + direction_mult * (reverse ? atan2(y - cy, x - cx) : atan2(x - cx, y - cy)) * (180.0 / 3.14159)) % 360);
    //piont.pixel = kbRGB_Angle_IntGet((x - cx), (y - cy));
	int16_t angle = kbRGB_XY2Angle(dx, dy);
    //angle = piont.angle/4.0f;
    //hue = (float)(progress + (int)(180 + direction_mult * (reverse ? atan2(y - cy, x - cx) : atan2(x - cx, y - cy)) * (180.0 / 3.14159)) % 360);
    hue = (_progress/kbRGB_PRE_MAX + (int)(360 + /*direction_mult **/(reverse ? angle>>KBRGB_XY2ANGLE_PRE : 90-(angle>>KBRGB_XY2ANGLE_PRE))) % 360);
    //hue = (float)(progress + (int)(180 + (atan2(x - cx, y - cy)) * (180.0 / 3.14159)) % 360);
    //hue = (float)(progress + (int)(360 - angle) % 360);
    hsv_t hsv = { 0, 0, 0 };
    hsv.hue = (int)hue;
    hsv.saturation = 255;
    hsv.value = 255;

    return (hsv2rgb(&hsv));
}
void kbRGB_Int_ColorWheel(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)       // 色轮
{
//    float cx_shift_mult = 0.5f;//cx_shift / 100.f;
//    float cy_shift_mult = 0.5f;//cy_shift / 100.f;
//    double cx = (cols - 1) * cx_shift_mult;
//    double cy = (rows - 1) * cy_shift_mult;
//    const int16_t cx = (cols - 1)>>1;
//    const int16_t cy = (rows - 1)>>1;

    for (uint16_t col_id = 0; col_id < cols; col_id++)
    {
         for (uint16_t row_id = 0; row_id < rows; row_id++)
        {
            uint32_t color = ColorWheelEffect_GetColor(col_id, row_id, cols, rows, params->progress, !reverse);
            kbRGB_pset(col_id, row_id, color);
        }
    }
    params->progress += ((params->Speed+speed*15)<<kbRGB_PRE_BIT) / params->FPS;
}

/*************************************************************************************************\
|        DoubleRotatingRainbow [9]                                                                              |
\*************************************************************************************************/
void kbRGB_Int_DoubleRotatingRainbow_Init(struct kbRGB_Int_Params *const params)       // 双旋转彩虹
{
    params->Speed = 80-30;
    params->Slider2Val = 50;//20;
    params->Rainbow_DoubleRotatingRainbow.frequency = 5;
}
static uint32_t DoubleRotatingRainbow_GetColor(const uint16_t x, const uint16_t y, const int16_t cx, const int16_t cy, const int32_t angle, const int frequency, const uint32_t _time, const unsigned int Slider2Val, const int reverse)
{
    int16_t c = reverse? kbRGB_Cos_Int(-angle) : kbRGB_Cos_Int(angle);
    int16_t s = reverse? kbRGB_Sin_Int(-angle) : kbRGB_Sin_Int(angle);
    //c = c / kbRGB_SinMax;
    //s = s / kbRGB_SinMax;

    hsv_t hsv;

    hsv.hue = (int)( ((_time * Slider2Val)>>kbRGB_PRE_BIT) + 360 * (360+frequency * (y - cy) * c/kbRGB_SinMax + (56 - abs(x - cx)) * frequency * s/kbRGB_SinMax) / 128.0) % 360;
    hsv.value = 255;
    hsv.saturation = 255;

    return (hsv2rgb(&hsv));
}
 void kbRGB_Int_DoubleRotatingRainbow(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)       // 双旋转彩虹
{
    const int16_t cx = (cols - 1)>>1;
    const int16_t cy = (rows - 1)>>1;
    //uint32_t _time=time;
    //_time = kbrgb_Params.time;
    const int frequency = params->Rainbow_DoubleRotatingRainbow.frequency;
    const int32_t angle = params->progress>>kbRGB_PRE_BIT;
    for (uint16_t col_id = 0; col_id < cols; col_id++)
    {
        for (uint16_t row_id = 0; row_id < rows; row_id++)
        {
           uint32_t color = DoubleRotatingRainbow_GetColor(col_id, row_id, cx, cy, angle, frequency, params->time, params->Slider2Val, reverse);
           kbRGB_pset(col_id, row_id, color);
        }
    }
    //kbrgb_Params.time += 0.01 * Speed / (float) FPS;
    //_time += 0.01 * (Speed<<kbRGB_PRE_BIT) / (float) FPS;
    params->time += ((params->Speed+speed*10)<<kbRGB_PRE_BIT) / (params->FPS*100);
    params->progress += ((params->Speed+speed*10)<<kbRGB_PRE_BIT)*180/(KBRGB_PI*params->FPS*100);
    if(params->progress>(720<<kbRGB_PRE_BIT)) params->progress -= (720<<kbRGB_PRE_BIT);
}

/*************************************************************************************************\
|        Hypnotoad [9]                                                                              |
\*************************************************************************************************/
void kbRGB_Int_Hypnotoad_Init(struct kbRGB_Int_Params *const params)                  // Hypnotoad
{
    params->Speed = 50-15;
    params->Slider2Val = 50;
    params->progress = 1000.f;
    params->RainbowHypn.animation_speed = 10;//.f;
    params->RainbowHypn.color_rotation_speed = 50;//.f;
    params->RainbowHypn.animation_direction = 0;
    params->RainbowHypn.color_rotation_direction = 0;
    params->RainbowHypn.spacing = 1;
    params->RainbowHypn.thickness = 1;
}
static uint32_t Hypnotoad_GetColor(const uint16_t x, const uint16_t y, const int16_t w, const int16_t h, const struct kbRGB_Int_RainbowHypn_t *const Hypn, const int32_t _progress, const int reverse)
{
    int16_t animation_mult = /*0.01 * */(reverse ? -1.0 : 1.0) * Hypn->animation_speed * (Hypn->animation_direction == 0 ? 1 : -1);
    int16_t color_mult = /*0.01 * */(reverse ? -1.0 : 1.0) * Hypn->color_rotation_speed * (Hypn->color_rotation_direction == 0 ? -1 : 1);
    int16_t dx = w - x*2;
    int16_t dy = h - y*2;
//    double angle    = atan2(y - cy, x - cx) * 180 / 3.14159265359;
    //int16_t distance;// = sqrt(pow(cx - x, 2) + pow(cy - y, 2));
    //struct kbRGB_Pixel piont;
    //piont.pixel = kbRGB_Angle_IntGet((x - cx), (y - cy));
    int16_t angle = kbRGB_XY2Angle(dx, dy);
    //distance = piont.radius/(float)(0x1<<KBRGB_RADIUS_INT_PRE);
    uint32_t distance = kbRGB_XY2Radius(dx, dy);
    //double distance = piont.radius*0.5f;
    //float  value    = cos(animation_mult * distance / (0.1 * 100*(float) Hypn->spacing*(0x1<<KBRGB_RADIUS_INT_PRE))  + _progress/(float)kbRGB_PRE_MAX);
    //float  value    = cos(animation_mult * distance / (float)(10*(0x1<<KBRGB_RADIUS_INT_PRE)*Hypn->spacing)  + _progress/(float)kbRGB_PRE_MAX);
    //float  value    = kbRGB_Cos_Int((animation_mult * distance / (float)(10*(0x1<<KBRGB_RADIUS_INT_PRE)*Hypn->spacing)  + _progress/(float)kbRGB_PRE_MAX)*180/KBRGB_PI) / (float)kbRGB_SinMax;
    //int16_t  value    = (kbRGB_SinMax+kbRGB_Cos_Int((animation_mult * distance / (float)(10*(0x1<<KBRGB_RADIUS_INT_PRE)*Hypn->spacing)  + _progress/(float)kbRGB_PRE_MAX)*180/KBRGB_PI))>>1;// / (float)kbRGB_SinMax;
    //int16_t  value    = (kbRGB_SinMax+kbRGB_Cos_Int((animation_mult * distance / (float)(10*(0x1<<KBRGB_RADIUS_INT_PRE)*Hypn->spacing)  + _progress/(float)kbRGB_PRE_MAX)*120))>>1;// / (float)kbRGB_SinMax;
    int16_t  value    = (kbRGB_SinMax+kbRGB_Cos_Int((animation_mult * distance*12 / ((0x1<<KBRGB_XY2RADIUS_PRE)*Hypn->spacing)  + _progress*120/kbRGB_PRE_MAX)))>>1;// / (float)kbRGB_SinMax;

    hsv_t hsv;
    //hsv.value = pow((value + 1) * 0.5, (11 - Hypn->thickness)) * 255;
    //hsv.value = pow(value, (11 - Hypn->thickness)) * 255;
    //hsv.hue = abs((int)(angle + (distance>>KBRGB_ANGLE_INT_PRE) + _progress/(float)kbRGB_PRE_MAX * color_mult * Hypn->color_rotation_speed/100) % 360);
    hsv.hue = abs((int)(angle + (distance>>KBRGB_XY2RADIUS_PRE) + _progress * color_mult * Hypn->color_rotation_speed/(kbRGB_PRE_MAX*100)) % 360);
    hsv.saturation = 255;
    //hsv.value = (value + 1) * 0.5 * 255;
    hsv.value = value;// * 255;
    //hsv.saturation = (value + 1) * 0.5 * 255;

    return (hsv2rgb(&hsv));
}
void kbRGB_Int_Hypnotoad(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)                  // Hypnotoad
{
//    float cx_shift_mult = 0.5f;//cx_shift / 100.f;
//    float cy_shift_mult = 0.5f;//cy_shift / 100.f;
//    unsigned int width = cols;
//    unsigned int height = rows;

////    float cx = (width-1) * cx_shift_mult;
////    float cy = (height-1) * cy_shift_mult;
//    int16_t cx = (width-1) >> 1;
//    int16_t cy = (height-1) >> 1;

    //int reverse=1;
    for(uint16_t row_id = 0; row_id < rows; row_id++)
    {
        for(uint16_t col_id = 0; col_id <  cols; col_id++)
        {
            uint32_t color = Hypnotoad_GetColor(col_id, row_id, cols, rows, &params->RainbowHypn, params->progress, !reverse);
            kbRGB_pset(col_id, row_id, color);
        }
    }
    //kbRGB_progress +=  0.1 * (float) Speed / (float) FPS;
    params->progress +=  ((params->Speed+speed*10)<<kbRGB_PRE_BIT) / (10*params->FPS);
}

/*************************************************************************************************\
|        NoiseMap [9]                                                                             |
\*************************************************************************************************/
static const float frequency = 0.12;
static const float amplitude = 3.9;
static const float lacunarity = 0.75;
static const float persistence = 0.5;
void kbRGB_Int_NoiseMap_Init(struct kbRGB_Int_Params *const params)                   // 噪声地图
{
    struct kbRGB_Int_NoiseMap_t *const Map = &params->Rainbow_NoiseMap;
    params->Speed = 20-5;
	params->FPS  = 9;
    params->Slider2Val = 50;
    //ResetNoise();
    Map->octaves = 2;
    Map->motion = 0;
    Map->motion_speed = 1;
    SimplexNoise_Int_Init(&Map->Noise, frequency, amplitude, lacunarity, persistence);
    //ResetColors();
}

static uint32_t NoiseMap_GetColor(unsigned int x, unsigned int y, const float _progress, struct kbRGB_Int_NoiseMap_t *const Map)
{
    float x_shift = 0;
    float y_shift = 0;

    switch (Map->motion) {

    case 0: y_shift = Map->motion_speed * _progress; break;
    case 1: y_shift = Map->motion_speed * -_progress;  break;
    case 2: x_shift = Map->motion_speed * _progress;  break;
    case 3: x_shift = Map->motion_speed * -_progress;  break;

    default: break;
    }


    float value = SimplexNoise_Int_fractal3d(&Map->Noise, Map->octaves, x + x_shift, y + y_shift, _progress);
    //float value = SimplexNoise_Int_fractal2d(&Map->Noise, Map->octaves, x + x_shift, y + y_shift);
    float frac = (1+value)*0.5;

    int color_choice = 0;//ui->colors_choice->currentIndex();
    hsv_t hsv;

    switch (color_choice)
    {
    case 0:
        hsv.hue = 360 * frac;
        hsv.saturation = 255;
        hsv.value = 255 ;
        return (hsv2rgb(&hsv));

    case 1:
        hsv.hue = 360 - 360 * frac;
        hsv.saturation = 255;
        hsv.value = 255 ;
        return (hsv2rgb(&hsv));

//    case 2:
//        int color_x = (1 - frac) * 100;
//        QColor c = image.pixelColor(color_x, 0);
//        return ColorUtils::fromQColor(c);
    }

    //return ColorUtils::OFF();
    return 0x00;
}
void kbRGB_Int_NoiseMap(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)                   // 噪声地图
{
    struct kbRGB_Int_NoiseMap_t *const Map = &params->Rainbow_NoiseMap;
    for (uint16_t col_id = 0; col_id < cols; col_id++)
    {
        for (uint16_t row_id = 0; row_id < rows; row_id++)
        {
            uint32_t color = NoiseMap_GetColor(col_id, row_id, params->progress/(float)(0x1<<kbRGB_PRE_BIT), Map);
            kbRGB_pset(col_id, row_id, color);
        }
    }
    params->progress += ((params->Speed+speed*5)<<kbRGB_PRE_BIT) / (params->FPS*10);
}

/*************************************************************************************************\
|        NoiseCircle [9]                                                                             |
\*************************************************************************************************/
void kbRGB_Int_NoiseCircle_Init(struct kbRGB_Int_Params *const params)                // 噪声地图
{
    struct kbRGB_Int_NoiseMap_t *const Map = &params->Rainbow_NoiseMap;
    params->Speed = 80;
	params->FPS  = 15;
    params->Slider2Val = 50;
    Map->octaves = 2;
    Map->motion = 0;
    Map->motion_speed = 1;
    //SimplexNoise_Init(&Noise, frequency, amplitude, lacunarity, persistence);
    SimplexNoise_Int_Init(&Map->Noise, frequency/5.5, amplitude, lacunarity/5.0, persistence);
}
static uint32_t NoiseCircle_GetColor(const uint16_t x, const uint16_t y, const int32_t cx, const int32_t cy, const float _progress, struct kbRGB_Int_NoiseMap_t *const Map)
{
    float x_shift = 0;
    float y_shift = 0;

    //struct kbRGB_Pixel piont;
    //piont.pixel = kbRGB_Angle_IntGet((x - cx), (y - cy));
	int16_t angle = kbRGB_XY2Angle((x - cx), (y - cy));

    switch (Map->motion) {

    case 0: y_shift = Map->motion_speed * _progress; break;
    case 1: y_shift = Map->motion_speed * -_progress;  break;
    case 2: x_shift = Map->motion_speed * _progress;  break;
    case 3: x_shift = Map->motion_speed * -_progress;  break;

    default: break;
    }

    //double angle = piont.angle/(float)(0x1<<KBRGB_ANGLE_INT_PRE);
	angle = angle/(float)(0x1<<KBRGB_XY2ANGLE_PRE);
    angle = angle*KBRGB_PI/180;
    //double distance = sqrt(pow(cx - x, 2) + pow(cy - y, 2));
    //double distance = piont.radius/(float)(0x1<<KBRGB_RADIUS_INT_PRE);
	double distance = kbRGB_XY2Radius((x - cx), (y - cy)) / (float)(0x1<<KBRGB_XY2RADIUS_PRE);
    float value = SimplexNoise_Int_fractal2d(&Map->Noise, Map->octaves, distance*0.5, _progress);
    //float value = SimplexNoise_fractal2d(&Noise, octaves, distance, kbRGB_progress+angle/2.0f);
    //float value = SimplexNoise_fractal2d(&Noise, octaves, angle, kbRGB_progress+angle);
    //float value = SimplexNoise_fractal2d(&Noise, octaves, angle, kbRGB_progress+distance);
    //if(angle<0) angle=-angle; float value = SimplexNoise_fractal2d(&Noise, octaves, (distance+x)/(angle+3.5f+y), kbRGB_progress+angle);
    //float value = SimplexNoise_fractal2d(&Noise, octaves, angle, kbRGB_progress+angle/(distance+1));
    //if(angle<0) angle=-angle; float value = SimplexNoise_fractal2d(&Noise, octaves, angle, kbRGB_progress+(distance*angle)/(angle+1.5));
    //if(angle<0) angle=-angle; float value = SimplexNoise_fractal(&Noise, octaves, kbRGB_progress+(distance*angle)/(angle+1.5));
    //if(angle<0) angle=-angle; float value = SimplexNoise_fractal(&Noise, octaves, kbRGB_progress+(distance*angle+x)/(angle+1.5));
    //if(angle<0) angle=-angle; float value = SimplexNoise_fractal(&Noise, octaves, kbRGB_progress+(distance)/(angle+1.5));
    float frac = (1+value)*0.5;

    int color_choice = 0;//ui->colors_choice->currentIndex();
    hsv_t hsv;

    switch (color_choice)
    {
    case 0:
        hsv.hue = 360 * frac;
        //hsv.hue = (int)(360 * frac+angle)%360;
        //hsv.hue = (distance+0)*50/(angle+8.5f+0)+(kbRGB_progress+angle+(x+0)/(distance+3.0f))*30;
        hsv.hue = hsv.hue%360;
        hsv.saturation = 255;
        hsv.value = 255 ;
        return (hsv2rgb(&hsv));

    case 1:
        hsv.hue = 360 - 360 * frac;
        hsv.saturation = 255;
        hsv.value = 255 ;
        return (hsv2rgb(&hsv));

//    case 2:
//        int color_x = (1 - frac) * 100;
//        QColor c = image.pixelColor(color_x, 0);
//        return ColorUtils::fromQColor(c);
    }

    //return ColorUtils::OFF();
    return 0x00;
}
void kbRGB_Int_NoiseCircle(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)        // 噪声地图
{
    struct kbRGB_Int_NoiseMap_t *const Map = &params->Rainbow_NoiseMap;
    int32_t cx = ((cols<<0) - 1)>>1;// * 0.5;
    int32_t cy = ((rows<<0) - 1)>>1;// * 0.5;
    for (uint16_t col_id = 0; col_id < cols; col_id++)
    {
        for (uint16_t row_id = 0; row_id < rows; row_id++)
        {
            uint32_t color = NoiseCircle_GetColor(col_id, row_id, cx, cy, params->progress/(float)(0x1<<kbRGB_PRE_BIT), Map);
            kbRGB_pset(col_id, row_id, color);
        }
    }
    params->progress += ((params->Speed+speed*5)<<kbRGB_PRE_BIT) / (params->FPS*10);
}

/*************************************************************************************************\
|        RainbowWave [9]                                                                          |
\*************************************************************************************************/
void kbRGB_Int_RainbowWave_Init(struct kbRGB_Int_Params *const params)       // 彩虹波
{
    params->Speed = 100;
    params->Slider2Val = 15;
}
void kbRGB_Int_RainbowWave(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)       // 彩虹波
{
    int Width = params->Slider2Val;
    int32_t _progress = (int32_t)params->Progress;

    hsv_t HSVVal;
    HSVVal.saturation = 255;
    HSVVal.value      = 255;
    //int ColumnCount = cols;
    //int RowCount = rows;

    for (uint16_t col_id = 0; col_id < cols; col_id++)
    {
        int HUE;
        int RVRS = reverse;

        if (RVRS)
        {
            //HUE = ((_progress + (int)( (cols - 1) - col_id)) * Width);
            HUE = (_progress + ((cols - 1) - col_id) * Width);
        }
        else
        {
            //HUE = ((_progress + (int)col_id) * Width);
            HUE = (_progress + col_id * Width);
        }

        HSVVal.hue = HUE;
        uint32_t color = hsv2rgb(&HSVVal);

        for (uint16_t row_id = 0; row_id < rows; row_id++)
        {
            kbRGB_pset(col_id, row_id, color);
        }
    }
    if (params->Progress < 360)
    {
        params->Progress += ((params->Speed+speed*20) / (double)(params->FPS));
    }
    else if (params->Progress >= 360)
    {
        params->Progress -= 360;
        params->Progress += 1;
    }
}

/*************************************************************************************************\
|        Rainbow [9]                                                                              |
\*************************************************************************************************/
static uint32_t RadialRainbow_GetColor(const uint16_t x, const uint16_t y, const int16_t w, const int16_t h, const int32_t _progress, const unsigned int shape, const unsigned int Slider2Val, const int reverse)
{
    hsv_t hsv;
    //float width = Slider2Val * 0.5f;
    int32_t distance, distance2;
    //struct kbRGB_Pixel piont;
    int16_t dx = w - x*2;
    int16_t dy = h - y*2;
	
    if(shape == 0)
    {
        //distance = sqrt(pow(cx - x, 2) + pow(cy - y, 2));
        //piont.pixel = kbRGB_Angle_IntGet((x - cx), (y - cy));
        //distance = piont.radius;///(float)(0x1<<KBRGB_RADIUS_INT_PRE);
        /*distance  = abs(cy - y) *(1<<KBRGB_RADIUS_INT_PRE);
        distance2 = abs(cx - x) *(1<<KBRGB_RADIUS_INT_PRE);
        distance = kb_sqrt(distance*distance + distance2*distance2);*/
		distance = kbRGB_XY2Radius(dx, dy);
    }
    else if (shape == 1)
    {
        //distance = std::max<float>(fabs(cy - y), fabs(cx - x));
        distance = abs(dy);
        distance2 = abs(dx);
        if(distance<distance2) distance=distance2;
        distance = distance<<(8-1);
    }
    else
    {
        return 0x00;//ColorUtils::OFF();
    }

    //hsv.hue = distance * width + (reverse ? _progress:-_progress);
    hsv.hue = ((int)(distance * Slider2Val)>>(1+8)) + (reverse ? _progress:-_progress);
    hsv.hue %= 360;

    hsv.saturation = 255;
    hsv.value = 255;

    return (hsv2rgb(&hsv));
}
void kbRGB_Int_RadialRainbow_Init(struct kbRGB_Int_Params *const params)       // 径向彩虹
{
    params->Speed = 100;
    params->Slider2Val = 30;
    //params->progress = 360<<kbRGB_PRE_BIT;
	params->Progress = 360;
    params->Rainbow.shape = 0;
}
void kbRGB_Int_RadialRainbow(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)       // 径向彩虹
{
//    float cx_shift_mult = 0.5f;//cx_shift / 100.f;
//    float cy_shift_mult = 0.5f;//cy_shift / 100.f;
//    double cx = (cols - 1) * cx_shift_mult;
//    double cy = (rows - 1) * cy_shift_mult;
//    double cx = (cols - 1) >>1;
//    double cy = (rows - 1) >>1;

    for (uint16_t col_id = 0; col_id < cols; col_id++)
    {
        for (uint16_t row_id = 0; row_id < rows; row_id++)
        {
            uint32_t color = RadialRainbow_GetColor(col_id, row_id, cols, rows, params->Progress, params->Rainbow.shape, params->Slider2Val, reverse);
            kbRGB_pset(col_id, row_id, color);
        }
    }
    //kbRGB_progress += (float) Speed / (float) FPS;
    //params->progress += (params->Speed<<kbRGB_PRE_BIT) / (params->FPS);
	params->Progress += (double)(params->Speed+speed*10) / (double)(params->FPS);
}

/*************************************************************************************************\
|        RotatingRainbow [9]                                                                      |
\*************************************************************************************************/
void kbRGB_Int_RotatingRainbow_Init(struct kbRGB_Int_Params *const params)       // 旋转的彩虹
{
    params->Speed = 10;
    params->Slider2Val = 50;//30;
}
static uint32_t RotatingRainbow_GetColor(const uint16_t x, const uint16_t y, const int16_t cx, const int32_t cy, const int32_t angle, const uint32_t progress, const int reverse)
{
    int16_t c = reverse? kbRGB_Cos_Int(-angle) : kbRGB_Cos_Int(angle);
    int16_t s = reverse? kbRGB_Sin_Int(-angle) : kbRGB_Sin_Int(angle);
//    c = c/(float)kbRGB_SinMax;
//    s = s/(float)kbRGB_SinMax;

    hsv_t hsv;

    hsv.hue = (int)( progress + 360 + 360 * ((y - cy) * 2 * c + (x - cx) * 2 * s) / (64*kbRGB_SinMax)) % 360;
    hsv.value = 255;
    hsv.saturation = 255;

    return (hsv2rgb(&hsv));
}
void kbRGB_Int_RotatingRainbow(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)       // 旋转的彩虹
{
//    float cx = (cols - 1) * 0.5;
//    float cy = (rows - 1) * 0.5;
    int16_t cx = (cols - 1)>>1;
    int16_t cy = (rows - 1)>>1;
    int16_t angle = params->Progress*2*180/(KBRGB_PI);

    for (uint16_t col_id = 0; col_id < cols; col_id++)
    {
        for (uint16_t row_id = 0; row_id < rows; row_id++)
        {
           uint32_t color = RotatingRainbow_GetColor(col_id, row_id, cx, cy, angle, params->Progress * params->Slider2Val, reverse);
           kbRGB_pset(col_id, row_id, color);
        }
    }
    params->Progress += (double)(params->Speed+speed*5) / (double)(params->FPS*10);
}

/*************************************************************************************************\
|        SpectrumCycling [9]                                                                      |
\*************************************************************************************************/
void kbRGB_Int_SpectrumCycling_Init(struct kbRGB_Int_Params *const params)       // 光谱骑自行车
{
    params->Speed = 20;
    params->Slider2Val = 30;
//	params->FPS = 200;
}
void kbRGB_Int_SpectrumCycling(const uint16_t cols, const uint16_t rows, const uint8_t speed, const int reverse, struct kbRGB_Int_Params *const params)       // 光谱骑自行车
{
    hsv_t hsv;

    hsv.value = 255;
    hsv.saturation = 255;
    hsv.hue = (int)(params->Progress) % 360;

    uint32_t color = (hsv2rgb(&hsv));

    for (uint16_t col_id = 0; col_id < cols; col_id++)
    {
        for (uint16_t row_id = 0; row_id < rows; row_id++)
        {
           kbRGB_pset(col_id, row_id, color);
        }
    }

    //progress += (float) Speed / (float) FPS;
    params->Progress += (params->Speed+10*speed) / (double)(params->FPS);
    if(params->Progress>=360) params->Progress -= 360;
}
